#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <string.h>
#include <math.h>

#include "kernels/dios_ssp_mvdr/dios_ssp_mbeam_mvdr.h"
#include "kernels/dios_ssp_doa/dios_ssp_doa_api.h"

#define RAWM 6
#define MIC 4
#define FRAMESIZE 128
#define MBEAM 8
#define PROGRESS_BAR_LENGTH 50  // 进度条长度

// 格式化时间（秒 -> 时:分:秒）
void format_time(double seconds, char* buf, size_t buf_size) {
    int hours = (int)seconds / 3600;
    int minutes = (int)((int)seconds % 3600) / 60;
    int secs = (int)seconds % 60;
    snprintf(buf, buf_size, "%02d:%02d:%02d", hours, minutes, secs);
}

// 单行刷新的tqdm风格进度条
void tqdm_single_line(int current, int total, double elapsed_time, double process_time) {
    if (current == 0) return;

    // 计算进度百分比和填充长度
    float progress = (float)current / total;
    int filled = (int)(progress * PROGRESS_BAR_LENGTH);

    // 估计总时间和剩余时间
    double total_est_time = (elapsed_time / current) * total;
    double remaining_time = total_est_time - elapsed_time;

    // 格式化时间字符串
    char elapsed_str[20], remaining_str[20];
    format_time(elapsed_time, elapsed_str, sizeof(elapsed_str));
    format_time(remaining_time, remaining_str, sizeof(remaining_str));

    // 计算处理速率和process占比
    double frame_rate = current / elapsed_time;
    float process_ratio = (elapsed_time > 0) ? (process_time / elapsed_time) * 100 : 0;

    // 核心：用\r回到行首，覆盖当前行内容（不换行）
    printf("\r");
    // 打印进度条
    printf("[");
    for (int i = 0; i < PROGRESS_BAR_LENGTH; i++) {
        if (i < filled) printf("█");
        else printf(" ");
    }
    printf("] ");
    // 打印其他信息（百分比、帧数、速率等）
    printf("%3d%% | 帧: %d/%d | 速率: %.2f帧/秒 | 耗时: %s | 剩余: %s | process占比: %.1f%%",
           (int)(progress * 100), current, total, frame_rate,
           elapsed_str, remaining_str, process_ratio);
    fflush(stdout);  // 强制刷新缓冲区，确保实时显示
}

int main(int argc, char *argv[]) {
    if (argc != 3) {
        fprintf(stderr, "用法: %s <输入文件> <输出文件>\n", argv[0]);
        return -1;
    }

    void* st = NULL;
    st = (void*)calloc(1, sizeof(objmbeamMVDR));
    objmbeamMVDR* ptr = (objmbeamMVDR*)st;

    PlaneCoord pos[4];
    pos[0].x = 0.03f; pos[0].y = 0.0f; pos[0].z = 0.0f;
    pos[1].x = 0.0f; pos[1].y = 0.03f; pos[1].z = 0.0f;
    pos[2].x = -0.03f; pos[2].y = 0.0f; pos[2].z = 0.0f;
    pos[3].x = 0.0f; pos[3].y = -0.03f; pos[3].z = 0.0f;

    dios_ssp_mbeammvdr_init(ptr, 4, pos);
    dios_ssp_mbeammvdr_reset(ptr);

    FILE *fidmic = fopen(argv[1], "rb");
    if (!fidmic) { 
        perror("打开输入文件失败"); 
        return -1; 
    }
    fseek(fidmic, 0, SEEK_END); 
    int d2 = ftell(fidmic);
    fseek(fidmic, 0, SEEK_SET); 
    int d1 = ftell(fidmic);
    int nframes = (d2 - d1) / (FRAMESIZE * sizeof(short) * RAWM);
    if (nframes <= 0) {
        fprintf(stderr, "无效的帧数计算\n");
        fclose(fidmic);
        return -1;
    }
    printf("总帧数: %d\n开始处理...\n", nframes);  // 这两行是初始化信息，会换行

    FILE *fidbf = fopen(argv[2], "wb");
    if (!fidbf) { 
        perror("打开输出文件失败"); 
        fclose(fidmic);
        return -1; 
    }

    short inbuf[FRAMESIZE * RAWM] = {0};
    float xbuf[MIC * FRAMESIZE] = {0.0f};
    float ybuf[MBEAM * FRAMESIZE] = {0.0f};
    short outbuf[MBEAM * FRAMESIZE] = {0};

    // 计时变量
    clock_t total_start = clock();          // 总处理开始时间
    clock_t process_start, process_end;     // 单帧process计时
    double total_process_time = 0.0;        // process总耗时

    // 处理循环
    for (int n = 0; n < nframes; n++) {
        fread(inbuf, sizeof(short), RAWM * FRAMESIZE, fidmic);
        
        // 转换输入数据
        for (int i = 0; i < FRAMESIZE; i++) {
            for (int m = 0; m < MIC; m++) {
                xbuf[FRAMESIZE * m + i] = inbuf[RAWM * i + m] * 1.0f;
            }            
        }
        
        // 统计process耗时
        process_start = clock();
        dios_ssp_mbeammvdr_process(ptr, xbuf, ybuf, 95);
        process_end = clock();
        total_process_time += (double)(process_end - process_start) / CLOCKS_PER_SEC;

        // 转换输出数据
        for (int i = 0; i < FRAMESIZE; i++) {
            for (int m = 0; m < MBEAM; m++) {
                outbuf[MBEAM * i + m] = (short)ybuf[m * FRAMESIZE + i];
            }
        }
        fwrite(outbuf, sizeof(short), FRAMESIZE * MBEAM, fidbf);

        // 计算已用时间
        double elapsed_time = (double)(clock() - total_start) / CLOCKS_PER_SEC;

        // 单行刷新进度条（每帧更新，覆盖当前行）
        tqdm_single_line(n + 1, nframes, elapsed_time, total_process_time);
    }

    // 处理完成后换行，避免后续输出与进度条重叠
    printf("\n\n处理完成！\n");
    double total_time = (double)(clock() - total_start) / CLOCKS_PER_SEC;
    printf("总耗时: %.2f秒 | 总帧数: %d\n", total_time, nframes);
    printf("Process总耗时: %.2f秒 (占比: %.1f%%)\n", 
           total_process_time, (total_process_time / total_time) * 100);
    printf("平均帧率: %.2f帧/秒 | 平均单帧process耗时: %.6f秒\n",
           nframes / total_time, total_process_time / nframes);

    fclose(fidmic); 
    fclose(fidbf);
    dios_ssp_mbeammvdr_delete(ptr);

    printf("mbeam beamformer test\n");
    return 0;
}




#if 0
#include <stdlib.h>
#include <stdio.h>
#include <time.h>  // 引入时间库

#include "kernels/dios_ssp_mvdr/dios_ssp_mbeam_mvdr.h"
#include "kernels/dios_ssp_doa/dios_ssp_doa_api.h"

#define RAWM 6
#define MIC 4
#define FRAMESIZE 128 
#define MBEAM 8

int main(int argc, char *argv[])
{
    // 记录总开始时间
    clock_t start_time = clock();

    void* st = NULL;
    st = (void*)calloc(1, sizeof(objmbeamMVDR));
    objmbeamMVDR* ptr = (objmbeamMVDR*)st;

    PlaneCoord pos[4];
    pos[0].x = 0.03f; pos[0].y = 0.0f; pos[0].z = 0.0f;
    pos[1].x = 0.0f; pos[1].y = 0.03f; pos[1].z = 0.0f;
    pos[2].x = -0.03f; pos[2].y = 0.0f; pos[2].z = 0.0f;
    pos[3].x = 0.0f; pos[3].y = -0.03f; pos[3].z = 0.0f;

    dios_ssp_mbeammvdr_init(ptr, 4, pos);
    dios_ssp_mbeammvdr_reset(ptr);

    FILE *fidmic = fopen(argv[1], "rb");
    if (!fidmic) { perror("fopen mic failed"); return -1; }
    fseek(fidmic, 0, SEEK_END); 
    int d2 = ftell(fidmic);
    fseek(fidmic, 0, SEEK_SET); 
    int d1 = ftell(fidmic);
    int nframes = (d2 - d1) / (FRAMESIZE * sizeof(short) * RAWM);
    printf("total frames = %d\n", nframes);

    FILE *fidbf = fopen(argv[2], "wb");
    if (!fidbf) { perror("fopen bf failed"); return -1; }

    short inbuf[FRAMESIZE * RAWM] = {0};
    float xbuf[MIC * FRAMESIZE] = {0.0f};
    float ybuf[MBEAM * FRAMESIZE] = {0.0f};
    short outbuf[MBEAM * FRAMESIZE] = {0};

    // 统计核心处理函数总耗时
    clock_t process_func_total = 0;  // 累加所有帧的process函数耗时
    clock_t frame_start, frame_end;  // 单帧process函数的开始/结束时间

    // 统计循环内总耗时（可选，用于对比）
    clock_t loop_start = clock();

    for (int n = 0; n < nframes; n++) {
        fread(inbuf, sizeof(short), RAWM * FRAMESIZE, fidmic);
        
        // 转换输入数据
        for (int i = 0; i < FRAMESIZE; i++) {
            for (int m = 0; m < MIC; m++) {
                xbuf[FRAMESIZE * m + i] = inbuf[RAWM * i + m] * 1.0f;
            }            
        }
        
        // 单独统计dios_ssp_mbeammvdr_process的耗时
        frame_start = clock();
        dios_ssp_mbeammvdr_process(ptr, xbuf, ybuf, 95);
        frame_end = clock();
        process_func_total += (frame_end - frame_start);  // 累加当前帧的耗时
        
        // 转换输出数据
        for (int i = 0; i < FRAMESIZE; i++) {
            for (int m = 0; m < MBEAM; m++) {
                outbuf[MBEAM * i + m] = (short)ybuf[m * FRAMESIZE + i];
            }
        }
        fwrite(outbuf, sizeof(short), FRAMESIZE * MBEAM, fidbf);
    }

    // 计算循环内总耗时（可选）
    clock_t loop_end = clock();
    double loop_time = (double)(loop_end - loop_start) / CLOCKS_PER_SEC;

    // 计算process函数总耗时和单帧平均耗时
    double process_func_total_time = (double)process_func_total / CLOCKS_PER_SEC;
    double process_func_per_frame = process_func_total_time / nframes;

    fclose(fidmic);
    fclose(fidbf);
    dios_ssp_mbeammvdr_delete(ptr);

    // 计算总耗时
    clock_t end_time = clock();
    double total_time = (double)(end_time - start_time) / CLOCKS_PER_SEC;

    // 输出耗时结果
    printf("总耗时: %.6f 秒\n", total_time);
    printf("循环内总耗时（含I/O和数据转换）: %.6f 秒\n", loop_time);
    printf("dios_ssp_mbeammvdr_process总耗时: %.6f 秒\n", process_func_total_time);
    printf("dios_ssp_mbeammvdr_process单帧平均耗时: %.6f 秒\n", process_func_per_frame);
    printf("process函数占循环内耗时比例: %.2f%%\n", (process_func_total_time / loop_time) * 100);

    printf("mbeam beamformer test\n");
    return 0;
}
#endif

#if 0
#include <stdlib.h>
#include <stdio.h>

#include "kernels/dios_ssp_mvdr/dios_ssp_mbeam_mvdr.h"
#include "kernels/dios_ssp_doa/dios_ssp_doa_api.h"

#define RAWM 4
#define MIC 4
#define FRAMESIZE 128 // win = 512 1/4帧叠
#define MBEAM 8

int main(int argc, char *argv[])
{
    void* st = NULL;
	st = (void*)calloc(1, sizeof(objmbeamMVDR));
	objmbeamMVDR* ptr = (objmbeamMVDR*)st;

    PlaneCoord pos[4];
    pos[0].x = 0.03f; pos[0].y = 0.0f; pos[0].z = 0.0f;
    pos[1].x = 0.0f; pos[1].y = 0.03f; pos[1].z = 0.0f;
    pos[2].x = -0.03f; pos[2].y = 0.0f; pos[2].z = 0.0f;
    pos[3].x = 0.0f; pos[3].y = -0.03f; pos[3].z = 0.0f;

    dios_ssp_mbeammvdr_init(ptr, 4, pos);
    dios_ssp_mbeammvdr_reset(ptr);

    // void *doa_inst = dios_ssp_doa_init_api(4, pos);
    // dios_ssp_doa_reset_api(doa_inst);

    FILE *fidmic = fopen(argv[1], "rb");
    fseek(fidmic, 0, SEEK_END); int d2 = ftell(fidmic);
    fseek(fidmic, 0, SEEK_SET); int d1 = ftell(fidmic);
    int nframes = (d2-d1)/(FRAMESIZE*sizeof(short)*RAWM);
    printf("total frames = %d\n", nframes);
    FILE *fidbf = fopen(argv[2], "wb");

    short inbuf[FRAMESIZE*RAWM] = {0};
    float xbuf[MIC*FRAMESIZE] = {0.0f};
    float ybuf[MBEAM*FRAMESIZE] = {0.0f};
    short outbuf[MBEAM*FRAMESIZE] = {0};

    for (int n=0; n<nframes; n++) {
        fread(inbuf, sizeof(short), RAWM*FRAMESIZE, fidmic);
        for (int i=0; i<FRAMESIZE; i++) {
            for (int m=0; m<MIC; m++) {
                xbuf[FRAMESIZE*m+i] = inbuf[RAWM*i+m]*1.0f;
            }            
        }
        dios_ssp_mbeammvdr_process(ptr, xbuf, ybuf, 95);

        // float doa = dios_ssp_doa_process_api(doa_inst, xbuf, 1, 0);
        // fwrite(&doa, sizeof(float), 1, fidbf);
        // printf("frame = %d, doa = %.3f\n", n, doa);

        for (int i=0; i<FRAMESIZE; i++) {
            for (int m=0; m<MBEAM; m++) {
                outbuf[MBEAM*i+m] = (short)ybuf[m*FRAMESIZE+i];
            }
            // outbuf[i] = (short)ybuf[0*FRAMESIZE+i];
        }
        fwrite(outbuf, sizeof(short), FRAMESIZE*MBEAM, fidbf);
    }

    fclose(fidmic); fclose(fidbf);

    // dios_ssp_doa_uninit_api(doa_inst);

    dios_ssp_mbeammvdr_delete(ptr);

    printf("mbeam beamformer test\n");
    return 0;
}
#endif


